home *** CD-ROM | disk | FTP | other *** search
/ Acorn User: China / Acorn User China CD-ROM (UK) (Disc A) / Acorn User China CD-ROM (UK) (Disc A).bin / DEMON / MISC / NETLITE2.ARC / NET / c / SLIP < prev    next >
Encoding:
Text File  |  1993-03-27  |  6.5 KB  |  223 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "slip.h"
  11. #include "iface.h"
  12. #include "asy.h"
  13. #include "timer.h"
  14. #include "ip.h"
  15. #include "arc.h"
  16.  
  17. static int  slipq(struct interface *, struct mbuf *);
  18. static void asy_start(struct interface *);
  19. static struct mbuf *slip_encode(struct mbuf *);
  20. static struct mbuf *slip_decode(struct interface *, char);
  21.  
  22. /* Send routine for point-to-point slip
  23.  * This is a trivial function since there is no slip link-level header
  24.  */
  25. int slip_send(struct mbuf *data, struct interface *interface,
  26.               int32 gateway, char precedence, char delay,
  27.               char throughput, char reliability)
  28. {
  29.         gateway = gateway;
  30.         precedence = precedence;
  31.         delay = delay;
  32.         throughput = throughput;
  33.         reliability = reliability;
  34.  
  35.         if(interface == NULLIF){
  36.                 free_p(data);
  37.                 return -1;
  38.         }
  39.         return (*interface->raw)(interface,data);
  40. }
  41. /* Send a raw slip frame -- also trivial */
  42. int slip_raw(struct interface *interface, struct mbuf *data)
  43. {
  44.         /* Queue a frame on the slip output queue and start transmitter */
  45.         return slipq(interface,data);
  46. }
  47. /* Encode a raw packet in slip framing, put on link output queue, and kick
  48.  * transmitter
  49.  */
  50. static int slipq(struct interface *interface, struct mbuf *data)
  51. {
  52.         register struct slip *sp;
  53.         struct mbuf *bp;
  54.  
  55.         if((bp = slip_encode(data)) == NULLBUF)
  56.                 return -1;      
  57.  
  58.         sp = interface->slip;
  59.         enqueue(&sp->sndq,bp);
  60.         sp->sndcnt++;
  61.         if(sp->tbp == NULLBUF)
  62.                 asy_start(interface);
  63.         return 0;
  64. }
  65. /* Start output, if possible, on asynch device dev */
  66. static void asy_start(struct interface *interface)
  67. {
  68.         register struct slip *sp;
  69.         char *buffer;
  70.         int n;
  71.  
  72.         sp = interface->slip;
  73.  
  74.         if (sp->tbp == NULLBUF) {
  75.                 if (sp->sndq == NULLBUF)
  76.                        return; /* No work */
  77.  
  78.                 sp->tbp = dequeue(&sp->sndq);
  79.                 sp->sndcnt--;
  80.         }
  81.  
  82.         if ((n = (*interface->put)(interface->dev,sp->tbp->data,sp->tbp->cnt)) < sp->tbp->cnt)
  83.         {
  84.                 buffer = malloc(n);
  85.                 pullup(&sp->tbp, buffer, n);
  86.                 free(buffer);
  87.         }
  88.         else
  89.         {
  90.                 free_p(sp->tbp);
  91.                 sp->tbp = NULLBUF;
  92.         }
  93. }
  94. /* Encode a packet in SLIP format */
  95. static struct mbuf *slip_encode(struct mbuf *bp)
  96. {
  97.         struct mbuf *lbp;       /* Mbuf containing line-ready packet */
  98.         register char *cp;
  99.         char c;
  100.  
  101.         /* Allocate output mbuf that's twice as long as the packet.
  102.          * This is a worst-case guess (consider a packet full of FR_ENDs!)
  103.          */
  104.         lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  105.         if(lbp == NULLBUF){
  106.                 /* No space; drop */
  107.                 free_p(bp);
  108.                 return NULLBUF;
  109.         }
  110.         cp = lbp->data;
  111.  
  112.         /* Flush out any line garbage */
  113.         *cp++ = FR_END;
  114.  
  115.         /* Copy input to output, escaping special characters */
  116.         while(pullup(&bp,&c,1) == 1){
  117.                 switch(uchar(c)){
  118.                 case FR_ESC:
  119.                         *cp++ = FR_ESC;
  120.                         *cp++ = T_FR_ESC;
  121.                         break;
  122.                 case FR_END:
  123.                         *cp++ = FR_ESC;
  124.                         *cp++ = T_FR_END;
  125.                         break;
  126.                 default:
  127.                         *cp++ = c;
  128.                 }
  129.         }
  130.         *cp++ = FR_END;
  131.         lbp->cnt = cp - lbp->data;
  132.         return lbp;
  133. }
  134. /* Process incoming bytes in SLIP format
  135.  * When a buffer is complete, return it; otherwise NULLBUF
  136.  */
  137. static struct mbuf *slip_decode(struct interface *interface, char c)
  138. {
  139.         struct mbuf *bp;
  140.         register struct slip *sp;
  141.  
  142.         sp = interface->slip;
  143.         switch(uchar(c)){
  144.         case FR_END:
  145.                 bp = sp->rbp;
  146.                 sp->rbp = NULLBUF;
  147.                 sp->rcnt = 0;
  148.                 return bp;      /* Will be NULLBUF if empty frame */
  149.         case FR_ESC:
  150.                 sp->escaped = 1;
  151.                 return NULLBUF;
  152.         }
  153.         if(sp->escaped){
  154.                 /* Translate 2-char escape sequence back to original char */
  155.                 sp->escaped = 0;
  156.                 switch(uchar(c)){
  157.                 case T_FR_ESC:
  158.                         c = FR_ESC;
  159.                         break;
  160.                 case T_FR_END:
  161.                         c = FR_END;
  162.                         break;
  163.                 default:
  164.                         sp->errors++;
  165.                         break;
  166.                 }
  167.         }
  168.         /* We reach here with a character for the buffer;
  169.          * make sure there's space for it
  170.          */
  171.         if(sp->rbp == NULLBUF){
  172.                 /* Allocate first mbuf for new packet */
  173.                 if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  174.                         return NULLBUF; /* No memory, drop */
  175.                 sp->rcp = sp->rbp->data;
  176.         } else if(sp->rbp1->cnt == SLIP_ALLOC){
  177.                 /* Current mbuf is full; link in another */
  178.                 if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  179.                         /* No memory, drop whole thing */
  180.                         free_p(sp->rbp);
  181.                         sp->rbp = NULLBUF;
  182.                         sp->rcnt = 0;
  183.                         return NULLBUF;
  184.                 }
  185.                 sp->rbp1 = sp->rbp1->next;
  186.                 sp->rcp = sp->rbp1->data;
  187.         }
  188.         /* Store the character, increment fragment and total
  189.          * byte counts
  190.          */
  191.         *sp->rcp++ = c;
  192.         sp->rbp1->cnt++;
  193.         sp->rcnt++;
  194.         return NULLBUF;
  195. }
  196. /* Process SLIP line I/O */
  197. int doslip(struct interface *interface)
  198. {
  199.         char c;
  200.         struct mbuf *bp;
  201.         int16 dev;
  202.  
  203.         dev = interface->dev;
  204.         /* Process any pending input */
  205.         while((*interface->get)(dev,&c,1) != 0)
  206.         {
  207.                 if((bp = slip_decode(interface,c)) != NULLBUF)
  208.                         (*interface->slip->recv)(interface,bp);
  209.         }
  210.         /* Kick the transmitter if it's idle */
  211.         asy_start(interface);
  212.         return 0;
  213. }
  214. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  215.  * link level header
  216.  */
  217. void slip_recv(struct interface *interface, struct mbuf *bp)
  218. {
  219.         interface = interface;
  220.         /* By definition, all incoming packets are "addressed" to us */
  221.         ip_route(bp,0);
  222. }
  223.